home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Languages / MacGofer 0.22d / MacGofer Sources / mac_main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-08  |  24.7 KB  |  532 lines  |  [TEXT/MPS ]

  1. /*****************************************************************************
  2.  
  3.   main.c:  Copyright (c) Kevin Hammond 1993.   All rights reserved.
  4.   
  5.   This is the main module for the Gofer Mac interface. 
  6.   
  7.   The routines in this module handle initialisation, the main event loop
  8.   and top-level event dispatching.
  9.  
  10. *****************************************************************************/
  11.  
  12. #pragma segment GMain
  13.  
  14. #include "mac.h"
  15. #include <AppleEvents.h>
  16. #include <Errors.h>
  17.  
  18. CursHandle ibeamcurs, watchcurs;                /* Ibeam and Watch cursors             */
  19. CursHandle gccurs;                              /* Cursor used during GC             */
  20. CCrsrHandle gccursc;                /* Colour version of above             */
  21.  
  22. EventRecord myEvent;                /* Main event record                 */
  23. Boolean WNEAvailable      = FALSE;        /* WaitNextEvent available             */
  24. Boolean CCAvailable       = FALSE;        /* Colour Cursors available             */
  25. Boolean CIAvailable       = FALSE;        /* Colour Icons available             */
  26. Boolean HasAppleEvents    = FALSE;        /* Supports System-7 AppleEvents         */
  27. Boolean inForeground      = TRUE;        /* Are we in the background?             */
  28. Boolean MemoryInstalledOK = FALSE;        /* True once the memory's been initialised     */
  29. Boolean GoferInitialised  = FALSE;        /* True once the interface is initialised     */
  30. Boolean InterpreterInitialised  = FALSE;    /* True once Gofer's completely initialised     */
  31.  
  32. short  systemVersion = 0x0000;            /* System software version             */
  33. short  goferWDRefNum = 0;            /* Gofer's working directory's refnum         */
  34. short  gofervol = 0;                /* Gofer's "real" vRefNum             */
  35. long   goferdirID = 0;                /* Gofer's "real" dirID             */
  36. short  goferresfile = -1;            /* Gofer's resource file no.             */    
  37.  
  38. static RgnHandle cursorRgn;            /* Cursor region for WaitNextEvent         */
  39.  
  40. Boolean quit = FALSE;                /* Set when finished                 */
  41.  
  42. extern jmp_buf catch_error;            /* The error jump buffer, used by longjmp    */
  43.  
  44. Bool    USER_ABORT = FALSE;            /* Has the user Pressed CMD-.             */
  45. extern  Boolean EOFread;            /* Has the user Pressed CMD-ENTER         */
  46. extern  Boolean HandlingEvents;            /* Is the Programmer Handling Events in Gofer      */
  47.  
  48. int HeapPC =          DEFAULT_HEAP_PERCENTAGE;    /* % Remaining memory for Heap             */
  49. unsigned MinMemSize = DEFAULT_MIN_MEM_SIZE;    /* Minimum Memory to run in             */
  50. #define  MIN_INIT_SIZE    320000            /* Minimum Memory to start up             */
  51.  
  52. unsigned ExtraStack = 0;                /* How much extra stack to reserve on startup   */
  53.  
  54.  
  55. char *undoBuffer=NIL;                /* The characters which can be "undone"        */
  56.  
  57.  
  58. /* Forward declarations */
  59.  
  60. Boolean cursorkey();                /* Is this key a cursor key            */
  61. extern OSType preftype;                /* The type of the Gofer Preferences file    */
  62. extern Boolean scrapVisible;            /* Is the scrap (clipboard) window visible    */
  63. extern DescType savemethod;                     /* How to do global saves                       */
  64.  
  65.  
  66. /*****************************************************************************
  67.  
  68.     Interacting with our environment.
  69.  
  70. ******************************************************************************/
  71.  
  72.  
  73. /* 
  74.   ObtainEnvironment determines whether WaitNextEvent etc are available.
  75.   System 7 should use Gestalt -- KH 
  76. */
  77.  
  78. #define  WNETrapNumber  0xA860                     /* WaitNextEvent trap             */
  79. #define  CCTrapNumber   0xAA1B                     /* GetCCursor trap                 */
  80. #define  CITrapNumber   0xAA1E                     /* GetCIcon trap                */
  81.  
  82. extern savedir(short vrefnum, long dirID, Boolean reset);
  83.  
  84. ObtainEnvironment()
  85. {
  86.   SysEnvRec environ;
  87.   Str255 goferVolName;
  88.  
  89.   /* If no default volume, use Gofer's folder  */
  90. //  if(GetVol(goferVolName, &goferWDRefNum) != noErr)
  91.   if(TRUE)
  92.     {
  93.        FCBPBRec fcb;
  94.        fcb.ioNamePtr = NULL;
  95.        fcb.ioCompletion = NULL;
  96.        fcb.ioVRefNum = 0;
  97.        fcb.ioRefNum = goferresfile;
  98.        fcb.ioFCBIndx = 0;
  99.        PBGetFCBInfo(&fcb,FALSE);
  100.        gofervol = fcb.ioFCBVRefNum;
  101.        goferdirID = fcb.ioFCBParID;
  102.     }
  103.   else
  104.      (void) getwdinfo(goferWDRefNum, &gofervol, &goferdirID);
  105.  
  106.   savedir(gofervol,goferdirID,TRUE);
  107.  
  108.   (void) SysEnvirons(1, &environ);                 /* How old is this system?             */
  109.  
  110.   if (environ.machineType < 0)                     /* Negative if really old             */
  111.     {
  112.       WNEAvailable = FALSE;
  113.       CCAvailable = FALSE;
  114.       CIAvailable = FALSE;
  115.       HasAppleEvents = FALSE;
  116.       systemVersion = 0x0000;
  117.     }
  118.   else
  119.     {
  120.       WNEAvailable = TrapAvailable(WNETrapNumber, ToolTrap);
  121.       CCAvailable =  TrapAvailable(CCTrapNumber,  ToolTrap);
  122.       CIAvailable =  TrapAvailable(CITrapNumber,  ToolTrap);
  123.       systemVersion = environ.systemVersion;
  124.  
  125.       HasAppleEvents = systemVersion >= 0x0700;
  126.       if(HasAppleEvents)
  127.         InstallAEHandlers();
  128.     }
  129.  
  130.  if (WNEAvailable)
  131.       cursorRgn = NewRgn();
  132. }
  133.  
  134.  
  135.  
  136. /*****************************************************************************
  137.  
  138.     General event-handling code.
  139.  
  140. ******************************************************************************/
  141.  
  142.  
  143. /*
  144.   Disk Insertion event.
  145.  
  146.   Format the disk if an unformatted disk is inserted.
  147. */
  148.  
  149.  
  150. void DoDiskEvent()
  151. {
  152.   if (HiWord(myEvent.message) != noErr)
  153.     {
  154.        myEvent.where.h = ((qd.screenBits.bounds.right - qd.screenBits.bounds.left) / 2) - (304 / 2);
  155.        myEvent.where.v = ((qd.screenBits.bounds.bottom - qd.screenBits.bounds.top) / 3) - (104 / 2);
  156.  
  157.        InitCursor();
  158.        (void) DIBadMount(myEvent.where, myEvent.message);
  159.      }
  160. }
  161.  
  162.  
  163.  
  164. /*
  165.   Handle menus -- whether from mouse downs or keys.
  166. */
  167.  
  168. void DoMenu(result,modifiers)
  169. long result;
  170. short modifiers;
  171. {
  172.   short menu = HiWord(result);
  173.   short item = LoWord(result);
  174.  
  175.   if (menu != 0 && item != 0)
  176.     {
  177.       Handle_Gofer_Menu(menu, item, modifiers);
  178.       drawcursor(myEvent, FALSE);
  179.       AdjustMenus(FALSE);
  180.     }
  181. }
  182.  
  183.  
  184.  
  185. /*
  186.     Window Zooming -- Macintosh System 3.2 or Later.
  187. */
  188.  
  189.  
  190. void DoZoom(whichWindow, code)
  191. WindowPtr whichWindow;
  192. short code;
  193. {
  194.   if (whichWindow != NIL)
  195.     {
  196.       if (TrackBox(whichWindow, myEvent.where, code) == TRUE)   
  197.         {
  198.           GrafPtr saveport;
  199.  
  200.           GetPort(&saveport);
  201.           SetPort(whichWindow);
  202.           EraseRect(&whichWindow->portRect);
  203.           ZoomWindow(whichWindow, code, TRUE);
  204.       SetPort(saveport);
  205.  
  206.           ResizeTheWindow(whichWindow);
  207.         }
  208.     }
  209. }
  210.  
  211.  
  212.  
  213. /*
  214.   Window resizing.
  215. */
  216.  
  217.  
  218. void DoGrow(whichWindow)
  219. WindowPtr  whichWindow;
  220. {
  221.   Rect  OldRect;
  222.   Rect  GrowRect;
  223.  
  224.   long  growResult;
  225.   short newWidth, newHeight;
  226.  
  227.   if (whichWindow != NIL)
  228.     {
  229.       /* Remember previous rectangle */
  230.       OldRect = whichWindow->portRect;
  231.  
  232.       /* Set the grow rectangle -- minimum 100x64; "infinite" maximum */
  233.       SetRect(&GrowRect, 100, 64, 32767, 32767);
  234.  
  235.       /* Get user input */
  236.       growResult = GrowWindow(whichWindow, myEvent.where, &GrowRect);
  237.       newWidth = LoWord(growResult);
  238.       newHeight = HiWord(growResult);
  239.  
  240.       /* If the new size is different from the previous one, resize the window appropriately */ 
  241.       if ( (newWidth != 0 && newHeight != 0)
  242.            && (newWidth != (OldRect.right - OldRect.left) || newHeight != (OldRect.bottom - OldRect.top)) )
  243.         {
  244.            GrafPtr saveport;
  245.  
  246.            GetPort(&saveport);
  247.            SetPort(whichWindow);
  248.            EraseRect(&whichWindow->portRect);
  249.            InvalRect(&whichWindow->portRect);
  250.        SetPort(saveport);
  251.  
  252.            SizeWindow(whichWindow, newWidth, newHeight, TRUE);
  253.            ResizeTheWindow(whichWindow);
  254.     }
  255.    }
  256. }
  257.  
  258.  
  259.  
  260. /*
  261.   Move a window.
  262. */
  263.  
  264. DoDrag(whichWindow) 
  265. WindowPtr  whichWindow;
  266. {
  267.   Rect  screenRect = qd.screenBits.bounds;
  268.   
  269.   SelectWindow(whichWindow);
  270.  
  271.   DragWindow(whichWindow, myEvent.where, &screenRect);
  272.  
  273.   MoveTheWindow(whichWindow);
  274. }
  275.  
  276.  
  277.  
  278. /*
  279.   Handle a press in a goaway box.
  280. */
  281.  
  282. DoGoAway(whichWindow)
  283. WindowPtr whichWindow;
  284. {
  285.   int windex;
  286.  
  287.   /* 
  288.       NB: This will not work for user-defined windows -- something
  289.       more sophisticated is needed.
  290.   */
  291.   if (TrackGoAway(whichWindow,myEvent.where))
  292.   
  293.     /* Normal Gofer window */
  294.     if((windex = findMyWindow(whichWindow))!=ILLEGAL_WINDOW)
  295.       {
  296.         if(myEvent.modifiers&optionKey)
  297.       IconiseWindow(windex);
  298.  
  299.         else if (closethewindow(windex,"closing"))
  300.           /* SKIP */;
  301.       }
  302.  
  303.     /* Desk accessory */
  304.     else if (((WindowPeek)whichWindow)->windowKind < 0)
  305.       {
  306.         CloseDeskAcc(((WindowPeek)whichWindow)->windowKind);
  307.         thefrontwindow = ILLEGAL_WINDOW;
  308.       }
  309.  
  310.     /* User-defined window */
  311.     else
  312.       {
  313.         HideWindow(whichWindow);
  314.         thefrontwindow = ILLEGAL_WINDOW;
  315.       }
  316. }
  317.  
  318.  
  319.  
  320. /*
  321.   Handle a mouse click in the body of a window.
  322.  
  323.   Select the window if it's not the front window.
  324.   Handle the mouse click after selecting the window
  325.   only if the window is iconic (so select and drag is
  326.   one operation rather than two for iconic windows).
  327. */
  328.  
  329. DoInContent(whichWindow)
  330. WindowPtr whichWindow;
  331. {
  332.   int windex = findMyWindow(whichWindow);
  333.   if(!iconic(windex) && whichWindow != FrontWindow())
  334.     SelectWindow(whichWindow);
  335.   else
  336.     {
  337.        SetPort(whichWindow);
  338.        DoTheWindow(whichWindow,&myEvent);
  339.     }
  340. }
  341.  
  342.  
  343.  
  344. /*
  345.   Handle window update events.
  346. */
  347.  
  348. void DoUpdate()
  349. {
  350.   WindowPtr whichWindow = (WindowPtr)myEvent.message;
  351.  
  352.   UpdateTheWindow(whichWindow);
  353. }
  354.  
  355.  
  356.  
  357. /*
  358.   Handle window activation/deactivation.
  359. */
  360.  
  361.  
  362. void DoActivate()
  363. {
  364.   /* Copy scrap whenever we become active */
  365.   if (thefrontwindow == ILLEGAL_WINDOW)
  366.     {
  367.       TEFromScrap();
  368.       loadscrap();
  369.     }
  370.  
  371.   ActivateTheWindow((WindowPtr)myEvent.message,
  372.             (myEvent.modifiers & activeFlag) != 0);
  373.   drawcursor(myEvent,TRUE);
  374. }
  375.  
  376.  
  377.  
  378. /*
  379.   Handle an OS event, such as MultiFinder suspend/resume.
  380. */
  381.  
  382. void DoOSEvent()
  383. {
  384.   if((myEvent.message & osEvtMessageMask) == SuspResEvt)
  385.     {
  386.      inForeground = (myEvent.message & resumeFlag) != 0;
  387.  
  388.       if (inForeground)
  389.         {
  390.       /* Resume Gofer */
  391.       WindowPtr frontwp;
  392.  
  393.       /* We only copy the System scrap to the TextEdit scrap if we're requested to */
  394.       if (myEvent.message & convertClipboardFlag)
  395.         {
  396.           TEFromScrap();
  397.           loadscrap();
  398.         }
  399.  
  400.       /* If the scrap has been hidden, then show it */
  401.       if ( scrapVisible && !((WindowPeek)WINDOW(scrap))->visible )
  402.         ShowWindow(WINDOW(scrap));
  403.  
  404.       /* Activate the frontmost window if there is one and it belongs to us */
  405.       frontwp = FrontWindow();
  406.       if (frontwp != NIL && ((WindowPeek)frontwp)->windowKind > 0)
  407.         ActivateTheWindow(FrontWindow(),TRUE);
  408.     }
  409.       else
  410.         {
  411.        /* Suspend Gofer */
  412.       if(thefrontwindow != ILLEGAL_WINDOW)
  413.         ActivateTheWindow(WINDOW(thefrontwindow),FALSE);
  414.  
  415.       if(scrapVisible)
  416.         HideWindow(WINDOW(scrap));
  417.      }
  418.       AdjustMenus(FALSE);
  419.     }
  420. }
  421.  
  422.  
  423. /*
  424.   Handle a high-level Apple Event, such as open application, 
  425.   print document etc.
  426.  
  427.   System-7 specific.
  428. */
  429.  
  430. void DoHighLevelEvent()
  431. {
  432.   OSErr resultCode;
  433.  
  434.   resultCode = AEProcessAppleEvent(&myEvent);
  435.   if (resultCode != noErr)
  436.     {
  437.       char resultStr[10];
  438.       sprintf(resultStr,"%u",resultCode);
  439.       paramtext("",resultStr,"","");
  440.       StopAlert(Res_AppleEvent_Failed_Alert,NIL);
  441.     }
  442.   else
  443.     AdjustMenus(FALSE);
  444. }
  445.  
  446.  
  447.  
  448. /* K and M define memory sizes for convenience when setting heap etc. */
  449.  
  450. #define    K    1024
  451. #define    M    K*K
  452.  
  453. #define MASTER_BLOCKS    5            /* How many extra blocks of handles to allocate.  This is a guess    */
  454.  
  455. InitMemory()
  456. {
  457.   long maxblock;                 /* Largest block during startup            */
  458.   unsigned heapsize;                      /* Heap size as determined during initialisation    */
  459.   int i;
  460.  
  461.   /* Set the stack space according to the amount of heap available */  
  462.  
  463.   heapsize = GetApplLimit() - ApplicZone();
  464.  
  465.   if(ExtraStack == 0)
  466.     ExtraStack = heapsize >   2*M? heapsize/15:
  467.                heapsize >   1*M?        32*K:
  468.                heapsize > 800*K?        16*K:
  469.                heapsize > 600*K?         8*K:
  470.              heapsize > 400*K?         4*K:
  471.                                        0*K;
  472.  
  473.   if(ExtraStack > 0)
  474.     SetApplLimit(GetApplLimit()-ExtraStack);
  475.  
  476.   for(i=0;i<MASTER_BLOCKS;++i)  
  477.     MoreMasters();                            /* Allow more handles                */
  478.   MaxApplZone();                              /* Extend the heap up to its limit         */
  479.  
  480.   /* Before even trying to start up, check our memory size */
  481.   if((maxblock=MaxBlock()) < MIN_INIT_SIZE)
  482.     {
  483.       SysBeep(3);
  484.       exit(1);
  485.     }
  486. }
  487.  
  488.  
  489.  
  490. /*****************************************************************************
  491.  
  492.     The main Program.
  493.  
  494. ***************************balTextRect;
  495.       GrafPtr saveport;
  496.  
  497.       GetPort(&saveport);
  498.       SetPort(WINDOW(thefrontwindow));
  499.  
  500.       globalTextRect = (*TEHANDLE(thefrontwindow))->viewRect;
  501.       LocalToGlobalRect(&globalTextRect);
  502.  
  503.       if (PtInRect(event.where, &globalTextRect))
  504.         {
  505.           SetCursor(*ibeamcurs);
  506.           if (adjustRegion)
  507.         RectRgn(cursorRgn, &globalTextRect);
  508.         }
  509.       else
  510.         {
  511.           SetCursor(&(qd.arrow));
  512.         }
  513.  
  514.       SetPort(saveport);
  515.     }
  516. /* If we don't have an editable window, then we just need an arrow */
  517.   else
  518.     {
  519.       SetCursor(&(qd.arrow));
  520.       if (adjustRegion)
  521.         RectRgn(cursorRgn, &worldRect);
  522.     }
  523. }
  524.  
  525.  
  526.  
  527. safeexit(n)
  528. {
  529.   mprintf("\n{{Gofer interpreter exited, code %d}}\n",n);
  530.   longjmp(catch_error,n);
  531. }
  532.